use model_graph_common::config::get_peer_config;
use serde::{Serialize, Serializer};
use std::{collections::HashMap, sync::Mutex};
use tauri::{command, AppHandle, Runtime, State, Window};

use model_graph_types::{
    assistant::{
        chat::{ChatMessage, ChatOptions},
        shell::{
            BatchScriptRequestMessage, ShellRequestMessage, ShellRequestOptions,
            ShellResponseMessage,
        },
        tts::{TtsRequestMessage, TtsRequestOptions, TtsResponseMessage},
    },
    connector::{Connector, ExecuteOptions, QueryOptions},
    database::{DataSource, DatabaseType},
    modeling::Value,
};
use serde_json::Value as JsonValue;
use union_connector::UnionConnector;

#[derive(Debug, thiserror::Error)]
pub enum Error {
    #[error(transparent)]
    Anyhow(#[from] anyhow::Error),
}

impl Serialize for Error {
    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(self.to_string().as_ref())
    }
}

type Result<T> = std::result::Result<T, Error>;

#[derive(Default)]
pub struct ContextState(Mutex<HashMap<String, UnionConnector>>);

#[command]
pub async fn peer_id<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
) -> Result<(String, String)> {
    //获取到本机的peer_id
    let peer_config = get_peer_config().await?;
    //

    Ok((peer_config.peer_id, String::new()))
}

#[command]
pub async fn peer_login<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    token: String,
) -> Result<()> {
    let result = model_graph_peer::peer_login(&token).await;
    //

    Ok(())
}

#[command]
pub async fn peer_status<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
) -> Result<String> {
    let result = model_graph_peer::peer_status().await?;
    //
    Ok(serde_json::to_string(&result).map_err(|err| anyhow::anyhow!("{}", err))?)
}

#[command]
pub async fn peer_assistant_chat<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    messages: Vec<ChatMessage>,
    options: ChatOptions,
) -> Result<Vec<ChatMessage>> {
    let result = model_graph_peer::assistant::assistant_local_chat(messages, options).await?;
    //
    Ok(result)
}

#[command]
pub async fn peer_assistant_sv2tts<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    messages: TtsRequestMessage,
    local_path: String,
    options: TtsRequestOptions,
) -> Result<()> {
    let result =
        model_graph_peer::assistant::assistant_local_sv2tts(messages, local_path, options).await?;
    //
    Ok(())
}

#[command]
pub async fn peer_assistant_shell<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    messages: ShellRequestMessage,
    options: ShellRequestOptions,
) -> Result<ShellResponseMessage> {
    let result = model_graph_peer::assistant::assistant_local_shell(messages, options).await?;
    //
    Ok(result)
}

#[command]
pub async fn peer_assistant_batch_script<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    messages: BatchScriptRequestMessage,
    options: ShellRequestOptions,
) -> Result<ShellResponseMessage> {
    let result =
        model_graph_peer::assistant::assistant_local_batch_script(messages, options).await?;
    //
    Ok(result)
}

#[command]
pub async fn channel_pubsub_publish<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    topic: String,
    subscribers: Vec<String>,
) -> Result<()> {
    let result = model_graph_channel::pubsub::publish(&topic, subscribers).await?;
    //
    Ok(result)
}

#[command]
pub async fn channel_pubsub_publish_message<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    topic: String,
    message: String,
) -> Result<()> {
    let result = model_graph_channel::pubsub::publish_message(&topic, message).await?;
    //
    Ok(result)
}

#[command]
pub async fn channel_pubsub_subscribe<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    topic: model_graph_types::channel::pubsub::Topic,
) -> Result<()> {
    let result = model_graph_channel::pubsub::subscribe(topic).await?;
    //
    Ok(result)
}

#[command]
pub async fn channel_uicmd_response<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    request_id: u32,
    message: String,
) -> Result<()> {
    let result =
        model_graph_channel::data_channels::ui_request::put_response(request_id, message).await?;
    //
    Ok(result)
}

#[command]
pub async fn channel_uicmd_remote_request<R: Runtime>(
    _app: AppHandle<R>,
    _window: Window<R>,
    state: State<'_, ContextState>,
    peer_id: String,
    message: String,
    timout: Option<u32>,
) -> Result<String> {
    let timeout = timout.map_or(30000u64, |t| t as u64);
    let result =
        model_graph_channel::data_channels::ui_request::remote_request(peer_id, message, timeout)
            .await?;
    //
    Ok(result)
}
